using System;
using System.Linq;
using System.Text;
using BearUtil;

public static class DynamicNodeHelper
{
    /// <summary>
    /// 安置属性
    /// </summary>
    /// <param name="prop"></param>
    /// <returns></returns>
    public static string AssignProp(NodeProperty prop)
    {
        if (string.IsNullOrEmpty(prop.PropName))
            return "";

        string _params = "";
        switch (prop.Type)
        {
            case NodePropertyType.Int:
                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic int {1} = {2};\n",
                    prop.Desc,
                    prop.PropName,
                    prop.paramInt);
            case NodePropertyType.ArrayInt:
                _params = "new int[] { ";
                for (var i = 0; i < prop.paramInts.Length - 1; i++)
                {
                    _params += prop.paramInts[i];
                    _params += ",";
                }

                _params += prop.paramInts.LastOrDefault();
                _params += "}";

                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic int[] {1} = {2};\n",
                    prop.Desc,
                    prop.PropName,
                    _params);
            case NodePropertyType.String:
                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic string {1} = \"{2}\";\n",
                    prop.Desc,
                    prop.PropName,
                    prop.paramString);
            case NodePropertyType.ArrayString:
                _params = "new string[] { ";
                for (var i = 0; i < prop.paramStrs.Length - 1; i++)
                {
                    _params += $"\"{prop.paramStrs[i]}\"";
                    _params += ",";
                }

                _params += $"\"{prop.paramStrs.LastOrDefault()}\"";
                _params += "}";

                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic string[] {1} = {2};\n",
                    prop.Desc,
                    prop.PropName,
                    _params);

            case NodePropertyType.Boolean:
                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic bool {1} = {2};\n",
                    prop.Desc,
                    prop.PropName,
                    prop.paramBool.ToString().ToLower());
            case NodePropertyType.Float:
                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic float {1} = {2}f;\n",
                    prop.Desc,
                    prop.PropName,
                    prop.paramFloat);
            case NodePropertyType.Vector2:
                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic Vector2 {1} = new Vector2({2}f, {3}f);\n",
                    prop.Desc,
                    prop.PropName,
                    prop.paramVec2.x,
                    prop.paramVec2.y);
            case NodePropertyType.Direction:
                return string.Format(
                    "\t\t[LabelText(\"{0}\")]\n\t\tpublic ObjectDirection {1} = ObjectDirection.{2};\n",
                    prop.Desc,
                    prop.PropName,
                    ((ObjectDirection)(prop.paramInt == 0 ? 1 : prop.paramInt)));
            case NodePropertyType.Node:
                return string.Format("\t\t[LabelText(\"{0}\")]\n\t\tpublic XNode.Node[] {1};\n",
                    prop.Desc,
                    prop.PropName);
            case NodePropertyType.ActorID:
                return ActorContent(prop);
            case NodePropertyType.AudioPlayData:
                return AudioContent(prop);
            case NodePropertyType.Line:
                return LineContent(prop);
            default:
                // NodePropertyType.NewProperty
                var dp = CreateNewProperty.Instance.NewEnums.Find(e => e.Name == prop.Type.ToString());
                return dp == null ? "\t\t\n" : NewPropertyContent(prop, dp);
        }
    }

    public static string AssignSaveNode()
    {
        return "\t\tpublic override bool isSaved { get => true; } \n";
        ;
    }

    public static string LineContent(NodeProperty prop)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append(
            "\t\t[LabelText(\"文本 id\"), ValueDropdown(\"GetLineKey\", DropdownWidth = 300), OnValueChanged(\"switchContent\")]\n");
        sb.Append($"\t\tpublic string lines = \"{prop.paramString}\";\n");
        sb.Append("\t\t[HideLabel, TextArea, Sirenix.OdinInspector.ReadOnly]\n");
        sb.Append("\t\tpublic string _content;\n");
        sb.Append("\t\tprivate List<string> GetLineKey()\n\t\t{\n");
        sb.Append("\t\t\treturn  LanguageCtrl.Instance.Langs;\n\t\t}\n");
        sb.Append("\t\tprivate void switchContent(string lineKey)\n\t\t{\n");
        sb.Append("\t\t\t_content = LanguageCtrl.Instance.GetLineContent(lineKey);\n\t\t}\n");

        return sb.ToString();
    }

    public static string ActorContent(NodeProperty prop)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("\t\t[SerializeField, HideLabel, ValueDropdown(\"GetActors\"), OnValueChanged(\"setRoleId\")]\n");
        sb.Append("\t\tpublic ActorData _actor;\n");
        sb.Append("\t\tprivate ActorData[] GetActors()\n");
        sb.Append("\t\t{\n");
        sb.Append("\t\t\tvar storyGraph = ((graph as DialogGraph)?.owner.graph as StoryGraph);\n");
        sb.Append("\t\t\tif (storyGraph == null)\n");
        sb.Append("\t\t\t\tstoryGraph = graph as StoryGraph;\n");
        sb.Append("\t\t\tif (storyGraph != null)\n");
        sb.Append("\t\t\t{\n");
        sb.Append("\t\t\t\tvar series = StoriesSetting.Instance.FindSeriesByStoryGraph(storyGraph);\n");
        sb.Append("\t\t\t\treturn series.Actors.ToArray();\n");
        sb.Append("\t\t\t}\n");
        sb.Append("\t\t\treturn new ActorData[0];\n");
        sb.Append("\t\t}\n\n");
        sb.Append($"\t\t[LabelText(\"{prop.Desc}\")]\n\n");
        sb.Append($"\t\tpublic int {prop.PropName};\n");
        sb.Append("\t\tprivate void setRoleId(ActorData actor)\n" +
                  "\t\t{\n" +
                  $"\t\t\t{prop.PropName} = _actor.role_id;\n" +
                  "\t\t}\n");
        return sb.ToString();
    }

    private static string AudioContent(NodeProperty prop)
    {
        return "\t\t[HideLabel, ValueDropdown(\"GetAudioClip\", DropdownWidth = 300), OnValueChanged(\"SetValue\")]\n" +
               "\t\tpublic AudioClip audio;\n" +
               $"\t\t[LabelText(\"{prop.Desc}\"), HideInInspector]\n" +
               $"\t\tpublic string {prop.PropName} = \"{prop.paramString}\";\n" +
               $"\t\tpublic void SetValue(AudioClip clip) => {prop.PropName} = clip.name;\n" +
               "\t\tpublic List<AudioClip> GetAudioClip() { return AudioCtrl.Instance.Clips;}\n";
    }

    public static string NewPropertyContent(NodeProperty prop, DynamicProperty dp)
    {
        var tmpValue = $"value_{dp.Name.ToLower()}";
        var valueType = dp.PType.ToString().ToLower();

        var propChioce = $"\t\tpublic string _{tmpValue};\n";
        var propValue = $"\t\tpublic {valueType} {prop.PropName};\n";
        // 是否存在默认值
        if (prop.HasDefault() && !string.IsNullOrEmpty(prop.paramString))
        {
            PropertyContent content = null;
            switch (dp.PType)
            {
                case PropertyParamType.Int:
                    var d = Convert.ToInt32(prop.paramString);
                    content = dp.contents.Find(c => c.IntParam == d);
                    int value = content == null ? 0 : content.IntParam;
                    propValue = $"\t\tpublic {valueType} {prop.PropName} = {value};\n";
                    break;
                case PropertyParamType.String:
                    content = dp.contents.Find(c => c.StringParam.Equals(prop.paramString));
                    propValue = $"\t\tpublic {valueType} {prop.PropName} = \"{content?.StringParam}\";\n";
                    break;
                default:
                    break;
            }

            propChioce = $"\t\tpublic string _{tmpValue} = \"{content?.TypeDesc}\";\n";
        }

        return
            $"\t\t[HideLabel, ValueDropdown(\"Get{dp.Name}\", DropdownWidth = 300), OnValueChanged(\"Set{dp.Name}\")]\n" +
            propChioce +
            $"\t\t[LabelText(\"{prop.Desc}\"), HideInInspector]\n" +
            propValue +
            $"\t\tpublic void Set{dp.Name} (string propDesc) => {prop.PropName} = CreateNewProperty.Instance.GetPropertyContent(\"{dp.Name}\", _{tmpValue}).{dp.PType}Param;\n" +
            $"\t\tpublic List<string> Get{dp.Name} () \n" +
            "{ return CreateNewProperty.Instance.GetPropertyContentDesc(" +
            $"\"{dp.Name}\"); " +
            "}\n";
    }
}